package advanced.thread;

/**
 * 线程的同步
 * <p>
 * 控制多个线程对同一份资源的使用
 * 使线程安全
 * 线程会有自己的内存空间,独立于主线程
 * 线程在进行资源访问时, 如果不加以控制,这些资源可能会更新不统一
 *
 * <p>
 * 本文的例子中可能会出现负数, 或者重复数
 * <p>
 * <p>
 * <p>
 * //线程同步的要求
 * 1. 多个访问线程访问统一资源形成线程池队列
 * 2. 给资源加锁, 线程之间进行访问竞争,
 */


public class L10 {
    public static void main(String[] args) {
        UnSafeWeb12306 web = new UnSafeWeb12306();
        //多个代理
        new Thread(web, "码畜").start();
        new Thread(web, "码农").start();
        new Thread(web, "麻黄").start();
    }
}

class UnSafeWeb12306 implements Runnable {
    //票数
    private int ticketNums = 100;
    private boolean flag = true;

    @Override
    public void run() {
        test();
    }

    /**
     * 添加同步锁的方法, 保证线程安全
     * <p>
     * synchronized 锁的是this 指向的对象
     * <p>
     * 同步块 (目标更明确)
     * synchronized(obj){}  锁定的是obj 这个对象
     */
    public synchronized void test() {
        synchronized (this) {
            while (flag) {
                if (ticketNums <= 0) break;
                //模拟延时
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
            }
        }
    }
}

class SafeWeb12306 implements Runnable {

    //票数
    private int ticketNums = 10;
    private boolean flag = true;

    @Override
    public void run() {
        while (flag) {
            if (ticketNums < 0) break;
            //模拟延时
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
        }
    }
}
